package com.dl698.util;

import java.io.IOException;
import java.util.Arrays;

/**
 * 反向字节数组输出流
 * 从数组末尾向前写入数据
 * 
 * @author wind
 * @version 1.1.1
 */
public class ReverseByteArrayOutputStream {

    private byte[] buffer;
    private int index;
    private boolean automaticResize;

    public ReverseByteArrayOutputStream() {
        // 默认构造函数
    }

    /**
     * 设置缓冲区大小
     * 
     * @param bufferSize 缓冲区大小
     */
    public void setBufSize(int bufferSize) {
        this.buffer = new byte[bufferSize];
        this.index = bufferSize - 1;
        this.automaticResize = false;
    }

    /**
     * 设置缓冲区大小并指定是否自动调整大小
     * 
     * @param bufferSize      缓冲区大小
     * @param automaticResize 是否自动调整大小
     */
    public void setBufSize(int bufferSize, boolean automaticResize) {
        this.buffer = new byte[bufferSize];
        this.index = bufferSize - 1;
        this.automaticResize = automaticResize;
    }

    /**
     * 设置缓冲区
     * 
     * @param buffer 缓冲区数组
     */
    public void setBuf(byte[] buffer) {
        this.buffer = buffer;
        this.index = buffer.length - 1;
        this.automaticResize = false;
    }

    /**
     * 设置缓冲区和索引
     * 
     * @param buffer 缓冲区数组
     * @param index  起始索引
     */
    public void setBuf(byte[] buffer, int index) {
        this.buffer = buffer;
        this.index = index;
        this.automaticResize = false;
    }

    /**
     * 设置缓冲区、索引和自动调整大小选项
     * 
     * @param buffer          缓冲区数组
     * @param index           起始索引
     * @param automaticResize 是否自动调整大小
     */
    public void setBuf(byte[] buffer, int index, boolean automaticResize) {
        this.buffer = buffer;
        this.index = index;
        this.automaticResize = automaticResize;
    }

    /**
     * 写入字节数组
     * 
     * @param byteArray 要写入的字节数组
     * @throws IOException 如果缓冲区不足且不允许自动调整大小
     */
    public void writeByte(byte[] byteArray) throws IOException {
        if (buffer == null) {
            throw new IOException("buffer is null");
        }

        // 从数组末尾向前写入
        for (int i = byteArray.length - 1; i >= 0; i--) {
            if (index == -1) {
                if (automaticResize) {
                    resize();
                    buffer[index] = byteArray[i];
                } else {
                    throw new IOException("buffer.length = " + buffer.length);
                }
            } else {
                buffer[index] = byteArray[i];
            }
            index--;
        }
    }

    /**
     * 写入单个字节
     * 
     * @param data 要写入的字节
     * @throws IOException 如果缓冲区不足且不允许自动调整大小
     */
    public void write(int data) throws IOException {
        if (buffer == null) {
            throw new IOException("buffer is null");
        }

        if (index == -1) {
            if (automaticResize) {
                resize();
                buffer[index] = (byte) data;
            } else {
                throw new IOException("buffer.length = " + buffer.length);
            }
        } else {
            buffer[index] = (byte) data;
        }
        index--;
    }

    /**
     * 调整缓冲区大小
     */
    private void resize() {
        if (buffer == null) {
            throw new RuntimeException("buffer is null");
        }

        byte[] newBuf = new byte[buffer.length * 2];
        int copyLength = buffer.length - index - 1;
        System.arraycopy(buffer, index + 1, newBuf, buffer.length + index + 1, copyLength);
        index += buffer.length;
        buffer = newBuf;
    }

    /**
     * 获取写入的字节数组
     * 
     * @return 写入的字节数组
     */
    public byte[] getArray() {
        if (buffer == null) {
            throw new RuntimeException("buffer is null");
        }

        if (index == -1) {
            return buffer;
        }

        int subBufferLength = buffer.length - index - 1;
        byte[] subBuffer = new byte[subBufferLength];
        System.arraycopy(buffer, index + 1, subBuffer, 0, subBufferLength);
        return subBuffer;
    }

    /**
     * 重置输出流
     */
    public void reset() {
        if (buffer == null) {
            throw new RuntimeException("buffer is null");
        }
        index = buffer.length - 1;
    }

    /**
     * 获取当前索引
     * 
     * @return 当前索引
     */
    public int getIndex() {
        return index;
    }

    /**
     * 获取缓冲区
     * 
     * @return 缓冲区数组
     */
    public byte[] getBuffer() {
        return buffer;
    }
}